/*
 * main.cpp
 *Creational Pattern: SINGLETON
 *  Created on: Sep 14, 2011
 *      Author: gassa
 */

#include <string>
#include <iostream>
#include <fstream>
#include <map>
#include <utility>
#include <hash_map>
#include "../include/CUtilities.h"
#include "../include/config.h"

using namespace std;

struct termIdValue {
	int count;
	termIdValue(const int _count) : count(_count) {}
};

typedef map< size_t, map<size_t, termIdValue> > INVERTEDINDEXMAP;
//typedef map< size_t, string > INVERTEDINDEXMAP;

class InvertedIndexer {
private:
	static bool instanceFlag;
	static InvertedIndexer *builderInstance;
	int barrelNumber;
	int currentBarreal;
	config *configInstance;
	string dirPath;
	int barrelSize;
	map<char, int> barrelMapper;

	INVERTEDINDEXMAP* tempMap;
	int* postingListCounter;
	ofstream* barrelStream;
	int* barrelCounter;

//	INVERTEDINDEXMAP tempMap[];
//	int postingListCounter[];
//	ofstream barrelStream[];
//	int barrelCounter[];

	InvertedIndexer() {
		instanceFlag = true;
		configInstance = config::getInstance();
		CUtilities::string_to_number(barrelNumber, configInstance->getValue("barrel_number"));

		tempMap = new INVERTEDINDEXMAP[barrelNumber];
		postingListCounter = new int[barrelNumber];
		barrelStream = new ofstream[barrelNumber];
		barrelCounter = new int[barrelNumber];

		setBarrelNumberToMap();
		dirPath = configInstance->getValue("path_to_index_store_dir");
		for (int i = 0; i < barrelNumber; i++) {
			postingListCounter[i] = 0;
			barrelCounter[i] = 0;
			barrelStream[i].open(
					(dirPath + "/InvIndex/index.inv.00"
							+ CUtilities::number_to_string(i) + ".000.txt").c_str(),
					ios::out);
			if (!barrelStream[i].good()) {
				cout
						<< dirPath + "/InvIndex/index.inv.00"
						+ CUtilities::number_to_string(i) + ".000.txt" << "fail open!!!!" << endl;
			}
		}
	}

	void writePostingList(INVERTEDINDEXMAP::iterator iter, ofstream& stream);
	void writeIndexToFile();
	void loadBarrelFile(int barrelNumber, map<int, string>& container);
public:
	~InvertedIndexer() {
		instanceFlag = false;
		delete configInstance;
		delete tempMap;
		delete postingListCounter;
		delete barrelStream;
		delete barrelCounter;
	};


	static InvertedIndexer* getInstance();
	void addPostingList(size_t tid, size_t fid, string term);
	void flushInstance();
	void setCurrentBarrel(string term);
	void closeAll();
	void printMAP();
	void mergeIndex();
	void setBarrelNumberToMap();
};
